#ifndef __MAP_WIDGET_H__
#define __MAP_WIDGET_H__

#include <string>
#include <deque>

#include <QtCore>
#include <QtGui>
#include <QVBoxLayout>
#include <QTableWidget>
#include <QDialogButtonBox>
#include <QComboBox>
#include <QCheckBox>
#include <QFileDialog>
#include <QInputDialog>
#include <QHeaderView>

//#include <opencv2/core.hpp>

#include <mapwidget/opmapwidget.h>

#include "base/debug/debug_config.h"
#include "uav/UAS_types.h"
#include "uav/UAS.h"

#include "ui_controls.h"
#include "utils_qt.h"

using namespace mapcontrol;


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class MapWidget;


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class MsgBoardItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)

public:
    enum { Type = UserType + 50 };

    MsgBoardItem();

    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget);

    QRectF boundingRect() const;
    int type() const { return Type; }

    int setUASManager(UAS_Manager *u) { m_uasManager = u; }

protected:
    void timerEvent(QTimerEvent *event);

protected:
    UAS_Manager     *m_uasManager;
    int             w, h;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class StatusTextItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)

public:
    enum { Type = UserType + 51 };

    StatusTextItem();

    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget);

    QRectF boundingRect() const;
    int type() const { return Type; }

    int setUASManager(UAS_Manager *u) { m_uasManager = u; }

protected:
    void timerEvent(QTimerEvent *event);

protected:
    UAS_Manager     *m_uasManager;
    int             w, h;
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class VideoFrameItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)

public:
    enum { Type = UserType + 52 };

    VideoFrameItem(MapWidget *parent);

    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget);

    QRectF boundingRect() const;
    int type() const { return Type; }

    int setImage(QImage *img);
    //int setImage(cv::Mat *img);
    int setImageScale(double s);

    int updatePos(void);

protected:
    void timerEvent(QTimerEvent *event);

protected:
    MapWidget       *m_mapView;

    QImage          *m_img;                     ///< image
    double          m_imgScale;                 ///< video frame scale

    int             w, h;                       ///< widget width/height
    int             m_boardOffset;              ///< board offset value

    double          m_tmLastImage;              ///< last timestamp of image insertion
    double          m_tmUpdatePeriod;           ///< minminum update period
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class LogInfoItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_INTERFACES(QGraphicsItem)

public:
    enum { Type = UserType + 53 };

    LogInfoItem(MapWidget *parent);

    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget);

    QRectF boundingRect() const;
    int type() const { return Type; }

    int updatePos(void);
    int updateCanvas(void);

    int insertMessage(std::string &msg);

protected:
    void timerEvent(QTimerEvent *event);

protected:
    MapWidget       *m_mapView;

    int             w, h;                       ///< widget width/height
    int             m_boardOffset;              ///< board offset value

    QString         m_fontName;                 ///< font name
    int             m_fontSize;                 ///< font size
    double          m_lineSpace;                ///< line vertical space
    int             m_nLines;                   ///< line numbers

    typedef std::deque<std::string> StringQueue;
    StringQueue     m_stringQueue;

    typedef std::map<std::string, QPen> PenMap;
    PenMap          m_penMap;

    double          m_tmLastMsg;
    pi::Mutex       m_mutexMsgPop;

    double          m_tmLastUpdate;
    double          m_tmUpdatePeriod;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class MapWidget : public OPMapWidget
{
    Q_OBJECT

public:
    explicit MapWidget(QWidget *parent = 0);
    virtual ~MapWidget();

    void setConf(QSettings *conf);
    void syncConf(void);

    void reset(void);

    void setHome(internals::PointLatLng &p, double alt);
    void getHome(internals::PointLatLng &p, double &alt);

    void setGCS(internals::PointLatLng &p, double alt);
    void getGCS(internals::PointLatLng &p, double &alt);

    void gotoHome(void);
    void gotoGCS(void);


    int addMissionItem(AP_MissionItem &wp);
    int delMissionItem(AP_MissionItem &wp);

    int getWaypoints(AP_MissionArray &wpa);
    int setWaypoints(AP_MissionArray &wpa);


    int setUASManager(UAS_Manager *u);

    int setShowMsgBoard(bool s=true);
    int getShowMsgBoard(void) { if( m_giMsgBoard ) return 1; else return 0; }

    int setShowStatusText(bool s=true);
    int getShowStatusText(void) { if( m_giStatusText ) return 1; else return 0; }

    int setShowVideoFrame(bool s=true);
    int getShowVideoFrame(void) { if( m_giVideoFrame ) return 1; else return 0; }
    int setVideoFrame(QImage &img);
    //int setVideoFrame(cv::Mat *img);
    int setVideoFrameScale(double s);
    int setVideoFrameScaleUpDown(int updown);

    int setShowLogInfo(bool s=true);
    int getShowLogInfo(void) { if( m_giLogInfo ) return 1; else return 0; }

    int setGuidedTarget(double lat, double lng);
    int getGuidedTarget(double &lat, double &lng);


    void setFlightHeight(double h) {
        m_flightHeight = h;
    }

    int logMessageHandle(std::string &msg);

    int setupMenu(void);
    int setupExMenu(QMap<QString, QAction*> &mainMenu);
    int setupMainMenu(QVector<QMenu*> &menuList);

public:
    QMenu                   *m_popupMenu;

    QMap<QString, QAction*> m_actionMap;
    QAction* getAction(const QString &actName);

    QAction                 *m_actWaypointEnd;

protected:
    QSettings               *m_conf;

    MsgBoardItem            *m_giMsgBoard;
    StatusTextItem          *m_giStatusText;
    VideoFrameItem          *m_giVideoFrame;
    LogInfoItem             *m_giLogInfo;

    int                     m_homeShow;             ///< show or hide home
    double                  m_homeAlt;              ///< home altitude
    internals::PointLatLng  m_homePos;              ///< home position
    double                  m_homeSafearea;         ///< safe area

    int                     m_gcsShow;              ///< show or hide GCS
    double                  m_gcsAlt;               ///< GCS altitude
    internals::PointLatLng  m_gcsPos;               ///< GCS position
    double                  m_gcsSafearea;          ///< safe area

    int                     m_bSelectArea;
    internals::PointLatLng  m_pSelectArea1, m_pSelectArea2;

    double                  m_flightHeight;         ///< default flight height

    UAS_Manager             *m_uasManager;          ///< uas manager obj

    int                     m_videoFrameShowHide;   ///< video frame show/hide
    double                  m_videoFrameScale;      ///< video frame scale

signals:
    void        HomeSet(void);
    void        GCSSet(void);

public slots:
    void        actMoveTo(void);
    void        actSetTargetGlobal(void);
    void        actChangeHeight(void);
    void        actSetCircularFlight(void);
    void        actStopCircularFlight(void);

    void        actWaypoint_add(void);
    void        actWaypoint_del(void);
    void        actWaypoint_edit(void);
    void        actWaypoint_clear(void);
    void        actWPEdit(int num, WayPointItem *wp);
    void        actWaypoint_save(void);
    void        actWaypoint_load(void);

    void        actMapAccess_ServerAndCache(void);
    void        actMapAccess_Cache(void);
    void        actMapType_SelectMap(void);
    void        actCacheMap(void);

    void        actUAVTrail_clear(void);

    void        actSelectArea_beg(void);
    void        actSelectArea_end(void);
    void        actSelectArea_clear(void);

    void        actHome_Set(void);
    void        actHome_Safearea(void);
    void        actHome_ShowHide(void);

    void        actGCS_Set(void);
    void        actGCS_Safearea(void);
    void        actGCS_ShowHide(void);

    void        actGotoHome(void);
    void        actGotoGCS(void);

protected:
    void        mouseMoveEvent(QMouseEvent *event);
    void        mousePressEvent(QMouseEvent *event);
    void        mouseDoubleClickEvent(QMouseEvent *event);
    void        wheelEvent(QWheelEvent *event);
    void        resizeEvent(QResizeEvent *event);
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class MapType_Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit MapType_Dialog(QWidget *parent = 0);

    void setupUi(void);

    void setupMapType_list(void);

    void setMapType(core::MapType::Types t);
    core::MapType::Types getMapType(void);

public:
    QDialogButtonBox        *buttonBox;
    QLabel                  *labMapType;
    QComboBox               *cbMapType;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class WaypointEdit_Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit WaypointEdit_Dialog(QWidget *parent = 0);

    void setupUi(void);


    int setWaypoints(int idx,
                     QMap<int, mapcontrol::WayPointItem*> *wpMap,
                     int heightAltitude = 1);

    int updateWaypoints(void);

    void setReferenceAltitude(double alt);
    double getReferenceAltitude(void);


private:
    QVBoxLayout         *verticalLayout;
    UI_waypointEdit     *wpEdit;
    QDialogButtonBox    *buttonBox;
};


#endif // end of __MAP_WIDGET_H__
